<template>
  <div :style="{ width, height, position: 'relative', overflow: 'hidden' }">
    <!-- 低清模糊图 -->
    <div
      v-if="lowSrc"
      :style="{
        backgroundImage: `url(${lowSrc})`,
        backgroundSize: fit,
        backgroundPosition: position,
        width: '100%',
        height: '100%',
        filter: 'blur(20px)',
        transform: 'scale(1.05)',
        transition: 'opacity 0.6s ease',
        opacity: loaded ? 0 : 1,
        position: 'absolute',
        top: 0,
        left: 0
      }"
    />

    <!-- 高清图 -->
    <div
      :style="{
        backgroundImage: `url(${highSrc})`,
        backgroundSize: fit,
        backgroundPosition: position,
        width: '100%',
        height: '100%',
        transition: 'opacity 0.6s ease',
        opacity: loaded ? 1 : 0
      }"
    />

    <slot />
  </div>
</template>

<script lang="ts" setup>
import { ref, onMounted, defineProps } from "vue";

interface Props {
  src: string;
  width?: string | number;
  height?: string | number;
  fit?: "cover" | "contain" | "fill" | "none" | "scale-down";
  position?: string;
  lazy?: boolean;
  compress?: boolean;
  quality?: number;
}

const props = withDefaults(defineProps<Props>(), {
  width: "100%",
  height: "300px",
  fit: "cover",
  position: "center",
  lazy: true,
  compress: true,
  quality: 0.7
});

const loaded = ref(false);
const lowSrc = ref<string>("");
const highSrc = ref<string>("");

function resolveSrc(src: string) {
  if (!src) return "";
  if (/^https?:\/\//.test(src)) return src;
  if (src.startsWith("@/")) {
    return new URL(src.replace(/^@/, "/src"), import.meta.url).href;
  }
  if (src.startsWith("./") || src.startsWith("../")) {
    return new URL(src, import.meta.url).href;
  }
  return src;
}

/**
 * 生成低清模糊图
 */
async function generateLowRes(
  src: string,
  scale = 0.1,
  quality = 0.4
): Promise<string> {
  try {
    const path = resolveSrc(src);
    const blob = await fetch(path).then(r => r.blob());
    const bitmap = await createImageBitmap(blob);
    const canvas = document.createElement("canvas");
    canvas.width = Math.max(1, bitmap.width * scale);
    canvas.height = Math.max(1, bitmap.height * scale);
    const ctx = canvas.getContext("2d")!;
    ctx.drawImage(bitmap, 0, 0, canvas.width, canvas.height);
    return canvas.toDataURL("image/jpeg", quality);
  } catch (err) {
    console.warn("[ProgressiveBackground] 低清图生成失败:", err);
    return "";
  }
}

async function loadImage() {
  highSrc.value = resolveSrc(props.src);

  if (props.compress) {
    lowSrc.value = await generateLowRes(props.src);
  }

  // 加载高清图
  const img = new Image();
  img.src = highSrc.value;
  img.onload = () => {
    loaded.value = true;
  };
  img.onerror = () => {
    loaded.value = true;
  };
}

onMounted(() => {
  if (props.lazy && container.value) {
    const observer = new IntersectionObserver(
      entries => {
        entries.forEach(entry => {
          if (entry.isIntersecting) {
            loadImage();
            observer.disconnect();
          }
        });
      },
      { threshold: 0.1 }
    );
    observer.observe(container.value); // ✅ 正确：直接观察 container
  } else {
    loadImage();
  }
});

const width =
  typeof props.width === "number" ? `${props.width}px` : props.width;
const height =
  typeof props.height === "number" ? `${props.height}px` : props.height;
const fit = props.fit;
const position = props.position;
</script>
